#-*- coding:utf-8 -*-
# 第九章 I/O编程
import os

#1.)读取文件 -------------
#D:/workspace/python/learnpy/ 因为脚步执行是在C盘 所以要绝对路径

ROOT_PATH = "E:/zhh/mycode/python/learnpy/iofile/";
#获取当前路径
print('当前工作目录:',os.path.abspath(os.curdir))

f = open((ROOT_PATH+'test1.txt'),'r') #读取文件

#content = f.read();
#print(content)
lst = f.readlines() #把所有行当做数组返回
print("lst=",lst)
for lineStr in lst:
	print(lineStr)

f.close() #每次都要调用close函数 改为with读写可以不需要调用close函数

#在Python中，文件读写是通过open()函数打开的文件对象完成的。使用with语句操作文件IO是个好习惯。
with open(ROOT_PATH+'test2.txt','r') as f:
	print(f.read())

#2.)写文件 -------------
'''
with open(ROOT_PATH+'test3.txt','w') as f:
	print(f.write("这是我写进去的内容\n再来一行"))
'''

def writeFile(path,content):
	with open(path,"w") as f:	
		f.write(content)
def readFile(path):
	cnt = "";
	with open(path,'r') as f:
		cnt = f.read();
	
	return cnt
		
writeFile(ROOT_PATH+'test3.txt',"这是我写进去的内容啦啦\n再来两个")

#读写二进制模式用rb，wb
 #f = open('/Users/michael/test.jpg', 'rb')

#读取非utf-8字节码的需要传入字节码
 #f = open('/Users/michael/gbk.txt', 'r', encoding='gbk')

#3.)StringIO和BytesIO -------------

print("----------StringIO和BytesIO-----------")

#StringIO
from io import StringIO
f = StringIO();
n = f.write("hello") #返回字节数
n = f.write(" ") #返回字节数
n = f.write("world") #返回字节数

strVal = f.getvalue();#获取内部所有字符串
print("strVal=",strVal)

#按照行读取
f=StringIO("Hello!\nHi!\nGoodBye！");
while True:
	line = f.readline();	
	if line=="":
		break;
	print(line.strip()); #strip具体作用？这样看就是获取一行的内容

#BytesIO
from io import BytesIO;

f = BytesIO();
f.write("中午".encode('utf-8')) #写入的不是str，而是经过UTF-8编码的bytes。
print(f.getvalue())

#4.)操作文件和目录 -------------
import os;
print("操作系统类型:",os.name) #如果是posix，说明系统是Linux、Unix或Mac OS X，如果是nt，就是Windows系统。
#print(os.uname()) #注意uname()函数在Windows上不提供,os有些函数系根据操作系统来的

#获取环境变量
os.environ
#print(os.environ)
#根据key来获取环境变量值
#print(os.environ.get("path"))

#查看当前目录绝对路径

abspath  = os.path.abspath('.')
print("abspath=",abspath)

#创建目录的步骤

#拼接路径,可以解决不同系统路径符号不同的问题
mkdir = os.path.join(ROOT_PATH,'mkdir')
print("mkdir=",mkdir)
#创建

#os.mkdir(mkdir) #已经存在的目录不能重复创建 需要判断 os.path.exists

#删除路径

#os.rmdir(mkdir)

#拆分路径和拆分文件扩展名
txt1 = os.path.join(ROOT_PATH,"test1.txt")
print(os.path.split(txt1)) #这样可以把一个路径拆分为两部分，后一部分总是最后级别的目录或文件名

print(os.path.splitext(txt1))##这样可以把一个路径拆分为两部分，后一部分总是得到扩展名

#重命名和删除文件
oldn = txt1
newn = os.path.join(ROOT_PATH,"txt_1.txt")
#os.rename(oldn,newn)
#os.remove(newn)

#列出目录下的所有目录
alldir = [x for x in os.listdir(ROOT_PATH) if os.path.isdir(os.path.join(ROOT_PATH,x))]
print(alldir)

#列出所有txt文件
allFiles=[x for x in os.listdir(ROOT_PATH) if os.path.isfile(os.path.join(ROOT_PATH,x)) and os.path.splitext(os.path.join(ROOT_PATH,x))[1]=='.txt' ]
print(allFiles)

#5.)序列化和反序列化 -----------------

import pickle
'''
#复习 : dict的定义 
d1 = {'name':'周','age':20}
d2 = dict((['age',25],['name','kfz']))
d3= dict(age=25,name='kfz')
'''
d= dict((['age',25],['name','kfz'])) #初始化dict的办法之一
print('d=',d)
byte = pickle.dumps(d) #序列化,得到二进制数据
print("d_byte=",byte)

f = open(os.path.join(ROOT_PATH,'bty.txt'),'wb')
f.write(byte)
f.close() 

#注意: 可以使用  pickle.dump(d, f) 直接序列化并且写入文件

f = open(os.path.join(ROOT_PATH,'bty.txt'),'rb')
c = pickle.load(f)
f.close()
print('反序列化=',c)

'''
Pickle的问题和所有其他编程语言特有的序列化问题一样，就是它只能用于Python，
并且可能不同版本的Python彼此都不兼容，因此，只能用Pickle保存那些不重要的数据，
不能成功地反序列化也没关系。
'''

#6.)json -------------------
import json

djson = {'d':dict(name="Hello"),'str':'hello','arr':[1,2,"a"],"f":True,"None":None}

#ensure_ascii=False 中文不会以Unicode编码输出,该函数参数是关键字参数
js = json.dumps(djson,ensure_ascii=False) 
print('json串=',js)
jsPath = os.path.join(ROOT_PATH,'data.json');
writeFile(jsPath,js)

js_str = readFile(jsPath)
jsobj = json.loads(js_str) #反序列json串
print('jsobj=',jsobj['d'])

#7.)json 进阶 序列化自定义的类 ----------

class Student(object):
	def __init__(self,name,age,score):
		self.name = name;
		self.age = age;
		self.score = score;

s1 = Student("辉",20,75)

def std2Json(std):
	return dict(
		name = std.name,
		age = std.age,
		score = std.score
	)


#json序列化自定义类的方法
#1.
csjs1 = json.dumps(s1,default=std2Json,ensure_ascii=False) #通过自定义一个函数转换
#2.
csjs2 = json.dumps(s1,default=lambda obj: obj.__dict__,ensure_ascii=False) #lambda转换

print(csjs1,csjs2)

#json反序列化自定义类
def dict2student(d):
	return Student(d['name'],d['age'],d['score'])
	
std1 = json.loads(csjs2, object_hook=dict2student)
print("std1=",std1)

